#include "flutter_window.h"

#include <optional>
#include <flutter/standard_message_codec.h>
#include <flutter/encodable_value.h>
#include <flutter/basic_message_channel.h>

#include "flutter/generated_plugin_registrant.h"

FlutterWindow::FlutterWindow(const flutter::DartProject& project)
    : project_(project) {}

FlutterWindow::~FlutterWindow() {}

bool FlutterWindow::OnCreate() {
  if (!Win32Window::OnCreate()) {
    return false;
  }

  RECT frame = GetClientArea();

  flutter_controller_ = std::make_unique<flutter::FlutterViewController>(
      frame.right - frame.left, frame.bottom - frame.top, project_);

  if (!flutter_controller_->engine() || !flutter_controller_->view()) {
    return false;
  }

  RegisterPlugins(flutter_controller_->engine());
  SetChildContent(flutter_controller_->view()->GetNativeWindow());

  flutter_controller_->engine()->SetNextFrameCallback([&]() {
    this->Show();
  });
  flutter_controller_->ForceRedraw();

  // 创建 BasicMessageChannel<EncodableValue>
  auto channel = std::make_unique<
      flutter::BasicMessageChannel<flutter::EncodableValue>>(
      flutter_controller_->engine()->messenger(),
      "custom_window_channel",
      &flutter::StandardMessageCodec::GetInstance());

  // 正确的 handler 签名
  channel->SetMessageHandler(
      [this](const flutter::EncodableValue& message,
             const flutter::MessageReply<flutter::EncodableValue>& reply) {
        // message 是从 Dart 发来的值
        if (auto maybe_str = std::get_if<std::string>(&message)) {
          if (*maybe_str == "getMainWindowHandle") {
            HWND hwnd = GetHandle();
            int64_t hwnd_int = reinterpret_cast<int64_t>(hwnd);
            reply(flutter::EncodableValue(hwnd_int));
            return;
          }
        }
        // 其他情况或者不是预期命令就发回空（或者自定义错误值）
        reply(flutter::EncodableValue());
      });

  custom_channel_ = std::move(channel);

  return true;
}

void FlutterWindow::OnDestroy() {
  if (flutter_controller_) {
    flutter_controller_ = nullptr;
  }
  Win32Window::OnDestroy();
}

LRESULT FlutterWindow::MessageHandler(HWND hwnd,
                                      UINT const message,
                                      WPARAM const wparam,
                                      LPARAM const lparam) noexcept {
  if (flutter_controller_) {
    std::optional<LRESULT> result =
        flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam,
                                                      lparam);
    if (result) {
      return *result;
    }
  }

  switch (message) {
    case WM_FONTCHANGE:
      flutter_controller_->engine()->ReloadSystemFonts();
      break;
  }

  return Win32Window::MessageHandler(hwnd, message, wparam, lparam);
}

HWND FlutterWindow::GetNativeWindow() {
  return GetHandle();
}
